#include "Precomp.h"
#include "AllBindings.h"
#include "Entity.h"
#include "Tile.h"
#include "AnimatedSprite.h"
#include "Text.h"
#include "ResourceManager.h"
#include "Map.h"
#include "SQGame.h"
#include "Utils.h"

DECLARE_INSTANCE_TYPE_NOCOPY(Entity);
DECLARE_INSTANCE_TYPE_NOCOPY(Map);
DECLARE_INSTANCE_TYPE_NOCOPY(Text);
DECLARE_INSTANCE_TYPE_NOCOPY(SpriteBased);
DECLARE_INSTANCE_TYPE_NAME(sf::Vector2f,Vector2f);
DECLARE_ENUM_TYPE(Entity::EntityType);
DECLARE_INSTANCE_TYPE(AnimationProfile);
DECLARE_INSTANCE_TYPE_NOCOPY(AnimatedSprite);

int TextConstructor(HSQUIRRELVM v)
{
	Text* f = new Text();
	int r =  PostConstruct<Text>(v, f, noRelease<Text>);
	StackHandler sa(v);
	HSQOBJECT ho = sa.GetObjectHandle(1); // OT_INSTANCE
	SquirrelObject instance(ho);
	f->setObject(instance);
	return r;
}

int TileConstructor(const SQChar* path,HSQUIRRELVM v)
{
	Tile* f= new Tile(path);
	int r =  PostConstruct<Tile>(v, f, noRelease<Tile>);
	StackHandler sa(v);
	HSQOBJECT ho = sa.GetObjectHandle(1); // OT_INSTANCE
	SquirrelObject instance(ho);
	f->setObject(instance);
	return r;
}

int AnimatedSpriteConstructor(const SQChar* path,AnimationProfile* animprofile,float speed,HSQUIRRELVM v)
{
	AnimatedSprite* f= new AnimatedSprite(path,*animprofile,speed);
	int r =  PostConstruct<AnimatedSprite>(v, f, noRelease<Tile>);
	StackHandler sa(v);
	HSQOBJECT ho = sa.GetObjectHandle(1); // OT_INSTANCE
	SquirrelObject instance(ho);
	f->setObject(instance);
	return r;
}

int AnimationProfileConstructor(HSQUIRRELVM v)
{
	StackHandler sa(v);
	if(sa.GetParamCount()<1)
		return sq_throwerror(v,L"Not enough param");
	SquirrelObject table=sa.GetObjectHandle(2);
	if(table.GetType()!=OT_TABLE)
		return sq_throwerror(v,L"Wrong type of argument");
	int w, h, xoffset, yoffset, numFrameInRow, xGap, yGap, numFrame;
	w=table.GetInt(L"width");
	h=table.GetInt(L"height");
	yoffset=table.GetInt(L"yOffset");
	xoffset=table.GetInt(L"xOffset");
	xGap=table.GetInt(L"xGap");
	yGap=table.GetInt(L"yGap");
	numFrame=table.GetInt(L"numFrame");
	numFrameInRow=table.GetInt(L"numFrameInRow");
	AnimationProfile* i=new AnimationProfile(w, h, xoffset, yoffset, numFrameInRow, xGap, yGap, numFrame);
	return PostConstruct<AnimationProfile>(v, i, ReleaseClassPtr<AnimationProfile>::release);
}

void switchLayer(Entity* entity,const SQChar* layer)
{
	entity->switchLayer(entity->getCurrentMap()->getLayerByName(layer));
}

void bindEntity()
{
	SQClassDefNoConstructor<Entity>(L"Entity")
		.func(&Entity::remove,L"remove")
		.func(&Entity::setX,L"setX")
		.func(&Entity::setY,L"setY")
		.func(&Entity::getX,L"getX")
		.func(&Entity::getY,L"getY")
		.func(&Entity::getCenter,L"getCenter")
		.func(&Entity::setCenter,L"setCenter")
		.func(&Entity::getPosition,L"getPosition")
		.func(&Entity::setPosition,L"setPosition")
		.func(&Entity::getRotation,L"getRotation")
		.func(&Entity::setRotation,L"setRotation")
		.func(&Entity::getType,L"getType")
		.func(&Entity::gotoMap,L"gotoMap")
		.globMembFunc(&switchLayer,L"switchLayer")
		.enumInt(Entity::ANIMATED,L"ANIMATED")
		.enumInt(Entity::STATIC,L"STATIC")
		.enumInt(Entity::TEXT,L"TEXT")
		.enumInt(Entity::TILE,L"TILE");
	
	SQClassDefNoConstructor<SpriteBased,Entity>(L"SpriteBased");

	SQClassDef<Text,Entity>(L"Text")
		.staticFunc(&TextConstructor,L"constructor")
		.func(&Text::getText,L"getText")
		.func(&Text::setText,L"setText");

	SQClassDefNoConstructor<Tile,SpriteBased>(L"Tile")
		.staticFunc(&TileConstructor,L"constructor");
	
	SQClassDefNoConstructor<AnimationProfile>(L"AnimationProfile")
		.staticFuncVarArgs(&AnimationProfileConstructor,L"constructor");

	SQClassDefNoConstructor<AnimatedSprite,SpriteBased>(L"AnimatedSprite")
		.staticFunc(&AnimatedSpriteConstructor,L"constructor");
}